
package todolist.gui;

import java.awt.AWTException;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JOptionPane;

import todolist.personalization.ErrorMessages;
import todolist.util.TTS;
import todolist.util.Utils;

/**
 * Handling creation and control of app's display in System Tray. Singleton.
 * @author YouLi
 * @author Ivan
 */
public class SystemTrayIcon {
	
	// handle singleton instance

	private static SystemTrayIcon _objSysTrayIcon;
	
	public static SystemTrayIcon getInstance() {
		if (_objSysTrayIcon == null)
			_objSysTrayIcon = new SystemTrayIcon();
		return _objSysTrayIcon;
	}
	
	// member attributes

	private SystemTray _objSystemTray;
	private TrayIcon _objTrayIcon;
	private ArrayList<RestoreGUIListener> _objRestoreGUIList;
	
	private static final String FILENAME_TRAY_ICON = "trayIcon.png";
	
	private SystemTrayIcon() {
		_objSystemTray = null;
		_objTrayIcon = null;
		_objRestoreGUIList = new ArrayList<RestoreGUIListener>();
	}
	
	// listener methods
	
	public void addRestoreGUIActionListener(RestoreGUIListener pobjRGUIListener) {
		_objRestoreGUIList.add(pobjRGUIListener);
	}
	
	public boolean removeRestoreGUIActionListener(RestoreGUIListener pobjRGUIListener) {
		return _objRestoreGUIList.remove(pobjRGUIListener);
	}
	
	// tray icon methods
	
	/**
	 * To be invoked once.
	 */
	public void initSystemTrayIcon() {
		if (!SystemTray.isSupported())
			JOptionPane.showMessageDialog(
				null, ErrorMessages.ERR_TRAY_ICON_NOT_SUPPORTED, "Tray Icon", // parent, message, title, messageType, icon
				JOptionPane.WARNING_MESSAGE, null);
		Image objImage = createImage(FILENAME_TRAY_ICON);		
		if (objImage == null)
			return; // if image not found, abandon operation
		_objSystemTray = SystemTray.getSystemTray();
		_objTrayIcon = new TrayIcon(objImage);
		PopupMenu objPopupMenu = new PopupMenu();
		MenuItem objRestoreItem = new MenuItem("Restore");
		MenuItem objExitItem = new MenuItem("Exit");
		objRestoreItem.addActionListener(new RestoreListener());
		objExitItem.addActionListener(new ExitListener());
		objPopupMenu.add(objRestoreItem);
		objPopupMenu.add(objExitItem);
		_objTrayIcon.setPopupMenu(objPopupMenu);
		_objTrayIcon.addActionListener(new RestoreListener());
	}

	/**
	 * Handles display of Tray Icon.
	 */
	public String setTrayIconVisibility(boolean pblnVisible) {
		if (_objTrayIcon == null)
			return null;
		_objSystemTray.remove(_objTrayIcon); // always remove before adding to prevent duplication
		if (pblnVisible)
			try {
				_objSystemTray.add(_objTrayIcon);
			} catch (AWTException e) {
				JOptionPane.showMessageDialog(
					null, ErrorMessages.ERR_TRAY_ICON_FAILED_TO_ADD, "Tray Icon", // parent, message, title, messageType, icon
					JOptionPane.WARNING_MESSAGE, null);
			}
		return null;
	}
	
	// inner classes

	/**
	 * Inner class listener for Restore Menu Item click.
	 */
	private class RestoreListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent pobjEvent) {
			for (RestoreGUIListener objRGUIListener : _objRestoreGUIList)
				objRGUIListener.restoreGUI();
		}
	}
	
	/**
	 * Inner class listener for Exit Menu Item click.
	 */
	private class ExitListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent pobjEvent) {
			_objSystemTray.remove(_objTrayIcon);
			TTS.getInstance().dispose();
			System.exit(0);
		}
	}
	
	// private methods

	/**
	 * Creates and returns an image based on given file name.
	 * GUI prompt will already be shown on creation failure.
	 */
	private Image createImage(String pstrName) {
		ImageIcon objIcon = Utils.createImageIcon(pstrName, null);		
		if (objIcon == null)
			return null;
		return objIcon.getImage();
	}

}
